package com.train.daily.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.train.common.enums.impl.BizExceptionEnums;
import com.train.common.exception.GlobalException;
import com.train.common.resp.CommonResp;
import com.train.common.resp.PageResp;
import com.train.daily.dto.seat.DailyTrainSeatCountDTO;
import com.train.daily.dto.token.*;
import com.train.daily.mapper.DailyTrainSkTokenMapper;
import com.train.daily.po.DailyTrainSkTokenPO;
import com.train.daily.resp.token.DailyTrainSkTokenPageResp;
import com.train.daily.service.DailyTrainSeatService;
import com.train.daily.service.DailyTrainSkTokenService;
import com.train.daily.service.DailyTrainStationService;
import com.train.system.enums.impl.SeatTypeEnums;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author baitiaojun
 * @description 针对表【dailyTrainSkToken(秒杀令牌)】的数据库操作Service实现
 * @createDate 2025-03-20 00:19:41
 */
@Service
@RequiredArgsConstructor
public class DailyTrainSkTokenServiceImpl extends ServiceImpl<DailyTrainSkTokenMapper, DailyTrainSkTokenPO>
    implements DailyTrainSkTokenService {

    private final DailyTrainSkTokenMapper dailyTrainSkTokenMapper;

    private final DailyTrainStationService dailyTrainStationService;

    private final DailyTrainSeatService dailyTrainSeatService;

    @Override
    public void editDailyTrainSkToken(DailyTrainSkTokenEditDTO dailyTrainSkTokenEditDTO) {
        if (!dailyTrainSkTokenMapper.existsId(dailyTrainSkTokenEditDTO.getId())) {
            throw new GlobalException(BizExceptionEnums.EXP_DAILY_TRAIN_SK_TOKEN_NOT_EXISTS);
        }

        boolean isSaved = dailyTrainSkTokenMapper.updateDailyTrainSkToken(dailyTrainSkTokenEditDTO);
        if (!isSaved) {
            throw new GlobalException(BizExceptionEnums.EXP_EDIT_DAILY_TRAIN_SK_TOKEN);
        }
    }

    @Override
    public PageResp<DailyTrainSkTokenPageResp> pageList(DailyTrainSkTokenPageDTO dailyTrainSkTokenPageDTO) {
        return dailyTrainSkTokenMapper.pageList(dailyTrainSkTokenPageDTO);
    }

    @Override
    public void remove(Long id) {
        boolean isRemoved = this.removeById(id);
        if (!isRemoved) {
            throw new GlobalException(BizExceptionEnums.EXP_REMOVE_DAILY_TRAIN_SK_TOKEN);
        }
    }

    @Override
    public void generateDailyTrainSkToken(String date, List<String> trainCodes) {
        LocalDate localDate = LocalDate.parse(date);
        //删除当日的车次令牌
        if (dailyTrainSkTokenMapper.existsTrains(localDate, trainCodes)) {
            boolean isDeleted = dailyTrainSkTokenMapper.deleteTrainToken(localDate, trainCodes);
            if (!isDeleted) {
                throw new GlobalException(BizExceptionEnums.EXP_ADD_DAILY_TRAIN_SK_TOKEN);
            }
        }

        //查询每日到达车站(途径站+终点站)
        Map<String, Long> dailyTrainStationMap = dailyTrainStationService.countDailyTrainStation(localDate, trainCodes);

        //查询每日车厢座位数量
        Map<String, DailyTrainSeatCountDTO> dailyTrainSeatBOMap = dailyTrainSeatService.countDailyTrainSeat(localDate, trainCodes);

        //新增当日车次令牌
        List<DailyTrainSkTokenAddDTO> dailyTrainSkTokenList = new ArrayList<>();
        for (String trainCode : trainCodes) {
            for (String seatType : dailyTrainSeatBOMap.keySet()) {
                DailyTrainSeatCountDTO dailyTrainSeatCountDTO = dailyTrainSeatBOMap.get(seatType);
                DailyTrainSkTokenAddDTO dailyTrainSkTokenAddDTO = new DailyTrainSkTokenAddDTO();
                dailyTrainSkTokenAddDTO.setDate(localDate);
                dailyTrainSkTokenAddDTO.setTrainCode(trainCode);
                dailyTrainSkTokenAddDTO.setSeatType(dailyTrainSeatCountDTO.getSeatType());
                Long ticketCount = dailyTrainStationMap.get(trainCode) * dailyTrainSeatCountDTO.getCount();
                dailyTrainSkTokenAddDTO.setCount(ticketCount);
                dailyTrainSkTokenList.add(dailyTrainSkTokenAddDTO);
            }
        }

        List<DailyTrainSkTokenPO> dailyTrainSkTokenPOList = BeanUtil.copyToList(dailyTrainSkTokenList, DailyTrainSkTokenPO.class);
        DailyTrainSkTokenService dailyTrainSkTokenService = (DailyTrainSkTokenService) AopContext.currentProxy();
        boolean isSaved = dailyTrainSkTokenService.saveBatch(dailyTrainSkTokenPOList);
        if (!isSaved) {
            throw new GlobalException(BizExceptionEnums.EXP_ADD_DAILY_TRAIN_SK_TOKEN);
        }
    }

    /**
     * 扣减数据库中令牌数量, 判断售票是否卖光
     * @param dto
     */
    @Override
    public void decrementSkToken(DailyTrainSkTokenValidDTO dto) {
        String seatType = dto.getSeatType();
        if (dailyTrainSkTokenMapper.decrementSkToken(dto.getTrainCode(), dto.getDate(), seatType, dto.getDecrement()) == 0) {
            String message = SeatTypeEnums.getByCode(seatType).getMessage();
            throw new GlobalException(BizExceptionEnums.EXP_DAILY_TRAIN_SK_TOKEN_ZERO, message);
        }
    }

    /**
     * 获取数据库中剩余令牌
     * @param dto
     * @return
     */
    @Override
    public Long getSkToken(DailyTrainTokenQueryLeftDTO dto) {
        return dailyTrainSkTokenMapper.getSkToken(dto.getTrainCode(), dto.getDate(), dto.getSeatType());
    }
}




